﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Threading;

namespace QT.IO
{
    /// <summary>
    /// 无API读写INI
    /// </summary>
    public class INI
    {
        #region Attributes

        /// <summary>
        /// Ini文件路径
        /// </summary>
        private String t_Path = "Setting.ini";
        /// <summary>
        /// Ini文件路径
        /// </summary>
        public String Path
        {
            get { return this.t_Path; }
            set
            {
                this.t_Path = value.Trim();
                if (!File.Exists(this.t_Path))
                {
                    this.Text = "";
                }
                else
                {
                    this.OpenFile();
                }
            }
        }

        /// <summary>
        /// Ini文件内容
        /// </summary>
        private String t_Text = "";
        /// <summary>
        /// Ini文件内容
        /// </summary>
        public String Text
        {
            get { return this.t_Text.Trim(); }
            set { this.t_Text = value.Trim(); }
        }

        #endregion

        #region 构造函数

        /// <summary>
        /// 创建与Exe文件名相同的Ini文件
        /// </summary>
        public INI()
        {
        }

        /// <summary>
        /// 创建指定路径文件名Ini文件
        /// </summary>
        /// <param name="dPath">Ini文件路径</param>
        public INI(String dPath)
        {
            this.Path = dPath;
        }

        #endregion

        #region 方法

        /// <summary>
        /// 写入时格式化字符串
        /// </summary>
        /// <param name="dValue">字符串</param>
        /// <returns>String</returns>
        private String FormatWrite(String dValue)
        {
            return dValue == null ? "\\null" : dValue.Replace("\\", "\\\\").Replace("\t", "\\t").Replace("\n", "\\n").Replace("\r", "\\r").Replace("=", "\\=").Replace("[", "\\[").Replace("]", "\\]");
        }

        /// <summary>
        /// 读取时格式化字符串
        /// </summary>
        /// <param name="dValue">字符串</param>
        /// <returns>String</returns>
        private String FormatRead(String dValue)
        {
            return dValue == null || dValue == "\\null" ? null : dValue.Replace("\\t", "\t").Replace("\\n", "\n").Replace("\\r", "\r").Replace("\\=", "=").Replace("\\[", "[").Replace("\\]", "]").Replace("\\\\", "\\");
        }


        /// <summary>
        /// 读取硬盘文件内容，他会把换行符更换为微软换行模式。
        /// </summary>
        public void OpenFile()
        {
            try
            {
                using (FileStream aStream = new FileStream(this.Path, FileMode.Open))
                {
                    Byte[] aBytes = new Byte[(Int32)aStream.Length];
                    aStream.Read(aBytes, 0, (Int32)aStream.Length);
                    this.Text = Encoding.Default.GetString(aBytes, 0, aBytes.Length);
                    this.Text = new Regex(@"(\n|\r\n)").Replace(this.Text, "\r\n");
                }
            }
            catch
            {
                Thread.Sleep(200);
                MessageBox.Show("读取配置文件失败" + this.Path);
            }
        }

        /// <summary>
        /// 写入现有内容
        /// </summary>
        public void WriteFile()
        {
            WriteFile(this.Path);
        }

        /// <summary>
        /// 将现有内容写入硬盘文件路径
        /// </summary>
        /// <param name="dPath"></param>
        public void WriteFile(String dPath)
        {
            try
            {
                using (FileStream aStream = new FileStream(dPath, FileMode.Create))
                {
                    Byte[] aBytes = Encoding.Default.GetBytes(this.Text);
                    aStream.Write(aBytes, 0, aBytes.Length);
                }
            }
            catch
            {
                Thread.Sleep(200);
                MessageBox.Show("写入配置文件失败." + dPath);
            }
        }

        /// <summary>
        /// 写入数据到Ini内容中
        /// </summary>
        /// <param name="dGroup">组名</param>
        /// <param name="dName">名称</param>
        /// <param name="dValue">值</param>
        public void Write(String dGroup, String dName, String dValue)
        {
            String aLine = this.FormatWrite(dName) + "=" + this.FormatWrite(dValue);
            Match aMatch = Regex.Match(this.Text, @"(?<=(\r\n|^))\[" + this.FormatWrite(dGroup) + @"\]\r\n([^\u0000]*?)(?=(\r\n\[|$))", RegexOptions.IgnoreCase);
            if (aMatch.Success)
            {
                Match eMatch = Regex.Match(aMatch.Groups[2].Value, @"(?<=(\r\n|^))" + this.FormatWrite(dName) + @"\=([^\r\n]*?)(?=(\r\n|$))", RegexOptions.IgnoreCase);
                if (eMatch.Success)
                {
                    this.Text = this.Text.Substring(0, aMatch.Groups[2].Index + eMatch.Index) + aLine + this.Text.Substring(aMatch.Groups[2].Index + eMatch.Index + eMatch.Length);
                    return;
                }
                else
                {
                    Match rMatch = Regex.Match(aMatch.Groups[2].Value, @"((\r\n)*)$", RegexOptions.IgnoreCase);
                    if (rMatch.Success)
                    {
                        this.Text = this.Text.Substring(0, aMatch.Groups[2].Index + rMatch.Index) + "\r\n" + aLine + this.Text.Substring(aMatch.Groups[2].Index + rMatch.Index);
                        return;
                    }
                }
            }
            else
            {
                Match sMatch = Regex.Match(this.Text, @"((\r\n)*)$", RegexOptions.IgnoreCase);
                if (sMatch.Success)
                {
                    this.Text = this.Text.Substring(0, aMatch.Groups[2].Index + sMatch.Index) + "\r\n\r\n" + "[" + this.FormatWrite(dGroup) + "]" + "\r\n" + aLine + this.Text.Substring(aMatch.Groups[2].Index + sMatch.Index);
                    return;
                }
            }
        }

        /// <summary>
        /// 读取Ini内容
        /// </summary>
        /// <param name="dGroup">组名</param>
        /// <param name="dName">名称</param>
        /// <returns>返回数据，他是支持null的</returns>
        public String Read(String dGroup, String dName)
        {
            Match aMatch = Regex.Match(this.Text, @"(?<=(\r\n|^))\[" + this.FormatWrite(dGroup) + @"\]\r\n([^\u0000]*?)(?=(\r\n\[|$))", RegexOptions.IgnoreCase);
            if (aMatch.Success)
            {
                Match eMatch = Regex.Match(aMatch.Groups[2].Value, @"(?<=(\r\n|^))" + this.FormatWrite(dName) + @"\=([^\r\n]*?)(?=(\r\n|$))", RegexOptions.IgnoreCase);
                if (eMatch.Success)
                {
                    return FormatRead(eMatch.Groups[2].Value);
                }
            }
            return null;
        }

        /// <summary>
        /// 删除某个组
        /// </summary>
        /// <param name="dGroup">组名</param>
        public void DeleteGroup(String dGroup)
        {
            Match aMatch = Regex.Match(this.Text, @"(?<=(\r\n|^))(\[" + this.FormatWrite(dGroup) + @"\]\r\n([^\u0000]*?))((\r\n\[|$))", RegexOptions.IgnoreCase);
            if (aMatch.Success)
            {
                this.Text = this.Text.Substring(0, aMatch.Groups[2].Index) + this.Text.Substring(aMatch.Groups[2].Index + aMatch.Groups[2].Length + (aMatch.Groups[5].Value == "\r\n[" ? 2 : 0));
                return;
            }
        }

        #endregion
    }

    /// <summary>
    /// API读写INI
    /// </summary>
    public class INIFile
    {
        #region Attributes

        /// <summary>
        /// 声明ini文件名称
        /// </summary>
        public string filePath = "Setting.ini";

        #endregion

        #region API

        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);

        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

        #endregion

        #region 构造函数

        /// <summary>
        /// 不带参，查找目录下与主程序同文件名的INI文件
        /// </summary>
        public INIFile()
        {
        }

        /// <summary>
        /// 带参，指定INI文件路径
        /// </summary>
        /// <param name="iniPath"></param>
        public INIFile(string iniPath)
        {
            filePath = iniPath;
        }

        #endregion

        #region INI读写

        /// <summary>
        /// 写INI文件
        /// </summary>
        /// <param name="Section">Section</param>
        /// <param name="Key">Key</param>
        /// <param name="value">value</param>
        public long WriteInivalue(string Section, string Key, string value)
        {
            return WritePrivateProfileString(Section, Key, value, this.filePath);
        }

        /// <summary>
        /// 读INI文件
        /// </summary>
        /// <param name="Section">Section</param>
        /// <param name="Key">Key</param>
        /// <param name="Value">值</param>
        /// <returns>string</returns>
        public bool ReadInivalue(string Section, string Key, out string Value)
        {
            StringBuilder temp = new StringBuilder(1024);
            int i = GetPrivateProfileString(Section, Key, "读取配置文件失败", temp, 1024, this.filePath);

            if (temp.ToString() == "读取配置文件失败")
            {
                Value = "";
                return false;
            }
            else
            {
                Value = temp.ToString();
                return true;
            }
        }
      

        #endregion
    }
}
